/***************************************************************************//**
 * @file
 * @brief APIs and defines for the Price Client plugin.
 *******************************************************************************
 * # License
 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
 *******************************************************************************
 *
 * The licensor of this software is Silicon Laboratories Inc. Your use of this
 * software is governed by the terms of Silicon Labs Master Software License
 * Agreement (MSLA) available at
 * www.silabs.com/about-us/legal/master-software-license-agreement. This
 * software is distributed to you in Source Code format and is governed by the
 * sections of the MSLA applicable to Source Code.
 *
 ******************************************************************************/

// *******************************************************************
// * price-client.h
// *
// *
// * Copyright 2010 by Ember Corporation. All rights reserved.              *80*
// *******************************************************************

#ifndef SILABS_PRICE_CLIENT_H
#define SILABS_PRICE_CLIENT_H

#ifndef EMBER_AF_PLUGIN_PRICE_CLIENT_TABLE_SIZE
#define EMBER_AF_PLUGIN_PRICE_CLIENT_TABLE_SIZE 2
#endif //EMBER_AF_PLUGIN_PRICE_CLIENT_TABLE_SIZE

#define ZCL_PRICE_CLUSTER_DURATION_UNTIL_CHANGED                 0xFFFF
#define ZCL_PRICE_CLUSTER_PRICE_RATIO_NOT_USED                   0xFF
#define ZCL_PRICE_CLUSTER_GENERATION_PRICE_NOT_USED              0xFFFFFFFFUL
#define ZCL_PRICE_CLUSTER_GENERATION_PRICE_RATIO_NOT_USED        0xFF
#define ZCL_PRICE_CLUSTER_ALTERNATE_COST_DELIVERED_NOT_USED      0xFFFFFFFFUL
#define ZCL_PRICE_CLUSTER_ALTERNATE_COST_UNIT_NOT_USED           0xFF
#define ZCL_PRICE_CLUSTER_ALTERNATE_COST_TRAILING_DIGIT_NOT_USED 0xFF
#define ZCL_PRICE_CLUSTER_NUMBER_OF_BLOCK_THRESHOLDS_NOT_USED    0xFF
#define ZCL_PRICE_CLUSTER_PRICE_CONTROL_NOT_USED                 0x00

// Price Client Command Common Structure - common elements used in most price commands
// ==========================================================
#define UNSPECIFIED_PROVIDER_ID  0xFFFFFFFF   // Used to initialize provider ID for commands that don't support it.
#define UNSPECIFIED_DURATION  0xFFFFFFFF

typedef struct {
  uint32_t providerId;      // Unique identifier for the commodity provider.
  uint32_t issuerEventId;   // Unique identifier for the transaction, generated by the commodity provider.
  uint32_t startTime;       // The UTC time when the event should take effect.
  uint32_t durationSec;     // Duration of the event, in seconds.
  bool valid;          // Specifies whether the data at this index is valid or not.
} EmberAfPriceClientCommonInfo;

/*   FOR PASTING INTO NEW CODE:
   info.___.commonInfos[].providerId = UNSPECIFIED_PROVIDER_ID;
   info.___.commonInfos[].issuerEventId =
   info.___.commonInfos[].startTime =
   info.___.commonInfos[].durationSec = UNSPECIFIED_DURATION;
   info.___.commonInfos[].valid = true;

 */

// Price Client Command Specific Structures
// ==========================================================

typedef struct {
  uint32_t billingPeriodStartTime;
  uint32_t billingPeriodDuration;
  uint8_t  billingPeriodDurationType;
  uint8_t  tariffType;
} EmberAfPriceClientBillingPeriod;

typedef struct {
  uint32_t blockPeriodStartTime;  // Raw start time, before adjustments made by blockPeriodDurationType.
  uint32_t blockPeriodDuration;   // Raw duration, units specified by blockPeriodDurationType.
  uint8_t blockPeriodControl;
  uint8_t blockPeriodDurationType;
  uint8_t tariffType;
  uint8_t tariffResolutionPeriod;
} EmberAfPriceClientBlockPeriod;

typedef struct {
  uint32_t issuerTariffId;
  uint8_t  subPayloadControl;
  // following array's  max value was set to
  // EMBER_AF_PLUGIN_PRICE_CLIENT_MAX_NUMBER_BLOCK_THRESHOLDS
  // this did not seem to be correct, so I changed it
  uint8_t  tierNumberOfBlockThresholds[EMBER_AF_PLUGIN_PRICE_CLIENT_MAX_NUMBER_TIERS];
  uint8_t  blockThreshold[EMBER_AF_PLUGIN_PRICE_CLIENT_MAX_NUMBER_TIERS + 1][6 * (EMBER_AF_PLUGIN_PRICE_CLIENT_MAX_NUMBER_BLOCK_THRESHOLDS + 1)];
} EmberAfPriceClientBlockThreshold;

typedef struct {
  uint32_t calorificValue;
  uint8_t  calorificValueUnit;
  uint8_t  calorificValueTrailingDigit;
} EmberAfPriceClientCalorificValue;

typedef struct {
  uint8_t tariffType;
  uint32_t cO2Value;
  uint8_t  cO2ValueUnit;
  uint8_t  cO2ValueTrailingDigit;
} EmberAfPriceClientCo2Value;

typedef struct {
  uint32_t conversionFactor;
  uint8_t  conversionFactorTrailingDigit;
} EmberAfPriceClientConversionFactor;

typedef struct {
  uint16_t durationInMinutes;
  uint8_t  tariffType;
  uint8_t  cppPriceTier;
  uint8_t  cppAuth;
} EmberAfPriceClientCppEvent;

#define EMBER_AF_PLUGIN_PRICE_CLUSTER_MAX_CREDIT_PAYMENT_REF_LENGTH 20
typedef struct {
  uint32_t creditPaymentDueDate;
  uint32_t creditPaymentOverDueAmount;
  uint8_t  creditPaymentStatus;
  uint32_t creditPayment;
  uint32_t creditPaymentDate;
  uint8_t  creditPaymentRef[EMBER_AF_PLUGIN_PRICE_CLUSTER_MAX_CREDIT_PAYMENT_REF_LENGTH + 1];
} EmberAfPriceClientCreditPayment;

typedef struct {
  uint32_t conversionFactor;
  uint32_t currencyChangeControlFlags;
  uint16_t newCurrency;
  uint8_t  conversionFactorTrailingDigit;
} EmberAfPriceClientCurrencyConversion;

typedef struct {
  uint32_t issuerTariffId;
  uint8_t  numberOfLabels;
  uint8_t  tierIds[EMBER_AF_PLUGIN_PRICE_CLIENT_MAX_TIERS_PER_TARIFF];
  uint8_t  tierLabels[EMBER_AF_PLUGIN_PRICE_CLIENT_MAX_TIERS_PER_TARIFF][13];
} EmberAfPriceClientTierLabels;

// Price Client Command Tables
// ==========================================================

typedef struct {
  EmberAfPriceClientCommonInfo    commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_BILLING_PERIOD_TABLE_SIZE];
  EmberAfPriceClientBillingPeriod billingPeriod[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_BILLING_PERIOD_TABLE_SIZE];
} EmberAfPriceClientBillingPeriodTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_BLOCK_PERIOD_TABLE_SIZE];
  EmberAfPriceClientBlockPeriod blockPeriod[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_BLOCK_PERIOD_TABLE_SIZE];
} EmberAfPriceClientBlockPeriodTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_BLOCK_THRESHOLD_TABLE_SIZE];
  EmberAfPriceClientBlockThreshold blockThreshold[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_BLOCK_THRESHOLD_TABLE_SIZE];
} EmberAfPriceClientBlockThresholdTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CALORIFIC_VALUE_TABLE_SIZE];
  EmberAfPriceClientCalorificValue calorificValue[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CALORIFIC_VALUE_TABLE_SIZE];
} EmberAfPriceClientCalorificValueTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CO2_TABLE_SIZE];
  EmberAfPriceClientCo2Value   co2Value[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CO2_TABLE_SIZE];
} EmberAfPriceClientCo2ValueTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CONVERSION_FACTOR_TABLE_SIZE];
  EmberAfPriceClientConversionFactor conversionFactor[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CONVERSION_FACTOR_TABLE_SIZE];
} EmberAfPriceClientConversionFactorTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT];
  EmberAfPriceClientCppEvent   cppEvent[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT];
} EmberAfPriceClientCppEventTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CREDIT_PAYMENT_TABLE_SIZE];
  EmberAfPriceClientCreditPayment creditPayment[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CREDIT_PAYMENT_TABLE_SIZE];
} EmberAfPriceClientCreditPaymentTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CURRENCY_CONVERSION_TABLE_SIZE];
  EmberAfPriceClientCurrencyConversion currencyConversion[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_CURRENCY_CONVERSION_TABLE_SIZE];
} EmberAfPriceClientCurrencyConversionTable;

typedef struct {
  EmberAfPriceClientCommonInfo commonInfos[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_TIER_LABELS_TABLE_SIZE];
  EmberAfPriceClientTierLabels tierLabels[EMBER_AF_PRICE_CLUSTER_CLIENT_ENDPOINT_COUNT][EMBER_AF_PLUGIN_PRICE_CLIENT_TIER_LABELS_TABLE_SIZE];
} EmberAfPriceClientTierLabelsTable;

// Singular Price Client Structure for storing pricing information
// ==========================================================
typedef struct {
  EmberAfPriceClientBillingPeriodTable      billingPeriodTable;
  EmberAfPriceClientBlockPeriodTable        blockPeriodTable;
  EmberAfPriceClientBlockThresholdTable     blockThresholdTable;
  EmberAfPriceClientCalorificValueTable     calorificValueTable;
  EmberAfPriceClientCo2ValueTable           co2ValueTable;
  EmberAfPriceClientConversionFactorTable   conversionFactorTable;
  EmberAfPriceClientCppEventTable           cppEventTable;
  EmberAfPriceClientCreditPaymentTable      creditPaymentTable;
  EmberAfPriceClientCurrencyConversionTable currencyConversionTable;
  EmberAfPriceClientTierLabelsTable         tierLabelsTable;
} EmberAfPriceClientInfo;

//void emberAfPriceClusterClientInitCallback(uint8_t endpoint);

void emAfPluginPriceClientPrintInfo(uint8_t endpoint);
void emAfPluginPriceClientPrintByEventId(uint8_t endpoint, uint32_t issuerEventId);
void emAfPriceClearPriceTable(uint8_t endpoint);

/**
 * @brief Returns the block period table index with a matching eventId.
 *
 * @param endpoint The relevant endpoint.
 * @param issuerEventId The eventId that should be searched for in the block period table.
 * @return The index with a valid matching event ID.
 *
 **/
uint8_t emAfPriceGetBlockPeriodTableIndexByEventId(uint8_t endpoint, uint32_t issuerEventId);

/**
 * @brief Prints the information at the specified index of the block period table.
 *
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintBlockPeriodTableIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Returns the conversion factor table index with a matching eventId.
 *
 * @param endpoint The relevant endpoint.
 * @param issuerEventId The eventId that should be searched for in the conversion factor table.
 * @return The index with a valid matching event ID.
 *
 **/
uint8_t emAfPriceGetConversionFactorIndexByEventId(uint8_t endpoint, uint32_t issuerEventId);

/**
 * @brief Prints the information at the specified index of the conversion factor table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintConversionFactorEntryIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Returns the calorific value table index with a matching eventId.
 *
 * @param endpoint The relevant endpoint.
 * @param issuerEventId The eventId that should be searched for in the calorific value table.
 * @return The index with a valid matching event ID.
 *
 **/
uint8_t emAfPriceGetCalorificValueIndexByEventId(uint8_t endpoint, uint32_t issuerEventId);

/**
 * @brief Prints the information at the specified index of the calorific value table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintCalorificValueEntryIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Initializes the consolidated bills table.
 *
 * @param endpoint The relevant endpoint.
 *
 **/
void emberAfPriceInitConsolidatedBillsTable(uint8_t endpoint);

/**
 * @brief Returns the index of the currently active CO2 entry, or 0xFF
 * if no active entry can be found.
 *
 * @param endpoint The relevant endpoint.
 * @return The index of the active CO2 entry.
 *
 **/
uint8_t emberAfPriceClusterGetActiveCo2ValueIndex(uint8_t endpoint);

/**
 * @brief Returns the index of the currently active tier label table entry,
 * or 0xFF if no active entry can be found.
 *
 * @param endpoint The relevant endpoint.
 * @return The index of the active tier label table entry.
 *
 **/
uint8_t emAfPriceGetActiveTierLabelTableIndexByTariffId(uint8_t endpoint, uint32_t tariffId);

/**
 * @brief Prints the information at the specified index of the tier label table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintTierLabelTableEntryIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Prints the information at the specified index of the CO2 value table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintCo2ValueTablePrintIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Prints the tier label table.
 *
 **/
//void emAfPriceClientPrintTierLabelTable( void );

/**
 * @brief Returns the consolidated bill table index with a matching eventId.
 *
 * @param endpoint The relevant endpoint.
 * @param issuerEventId The eventId that should be searched for in the consolidated bill table.
 * @return The index with a valid matching event ID.
 *
 **/
uint8_t emAfPriceConsolidatedBillTableGetIndexWithEventId(uint8_t endpoint, uint32_t issuerEventId);

/**
 * @brief Returns the index of the active consolidated bill table.
 *
 * @param endpoint The relevant endpoint.
 * @return The index of the consolidated bills table with a valid matching event ID,
 * or 0xFF if no valid match is found.
 *
 **/
uint8_t emAfPriceConsolidatedBillTableGetCurrentIndex(uint8_t endpoint);

/**
 * @brief Prints the information at the specified index of the consolidated bill table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintConsolidatedBillTableIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Prints information about the CPP event.
 *
 * @param endpoint THe relevant endpoint.
 *
 **/
void emberAfPricePrintCppEvent(uint8_t endpoint);

/**
 * @brief Returns the credit payment table index with a matching eventId.
 *
 * @param issuerEventId The eventId that should be searched for in the credit payment table.
 * @return The index with a valid matching event ID.
 *
 **/
uint8_t emAfPriceCreditPaymentTableGetIndexWithEventId(uint8_t endpoint, uint32_t issuerEventId);

/**
 * @brief Prints the credit payment table entry data of the index with a valid matching eventId.
 *
 * @param endpoint The relevant endpoint.
 * @param issuerEventId The eventId that should be found in the credit payment table.
 *
 **/
void emAfPricePrintCreditPaymentTableEventId(uint32_t issuerEventId);

/**
 * @brief Prints the information at the specified index of the credit payment table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintCreditPaymentTableIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Returns the currency conversion table index with a matching eventId.
 *
 * @param endpoint The relevant endpoint.
 * @param issuerEventId The eventId that should be searched for in the currency conversion table.
 * @return The index with a valid matching event ID.
 *
 **/
uint8_t emberAfPriceClusterCurrencyConversionTableGetIndexByEventId(uint8_t endpoint, uint32_t issuerEventId);

/**
 * @brief Prints the information at the specified index of the currency conversion table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintCurrencyConversionTableIndex(uint8_t endpoint, uint8_t index);

/**
 * @brief Returns the index of the currently active currency conversion entry,
 * or 0xFF if no active entry can be found.
 *
 * @param endpoint The relevant endpoint.
 * @return The index of the active currency conversion entry.
 *
 **/
uint8_t emberAfPriceClusterGetActiveCurrencyIndex(uint8_t endpoint);

/**
 * @brief Returns the index of the currently active billing period entry,
 * or 0xFF if no active entry can be found.
 *
 * @param endpoint The relevant endpoint.
 * @return The index of the active billing period entry.
 *
 **/
uint8_t emAfPriceGetActiveBillingPeriodIndex(uint8_t endpoint);

/**
 * @brief Prints the information at the specified index of the billing period table.
 *
 * @param endpoint The relevant endpoint.
 * @param index The index whose data should be printed.
 *
 **/
void emAfPricePrintBillingPeriodTableEntryIndex(uint8_t endpoint, uint8_t index);

#endif  // #ifndef _PRICE_CLIENT_H_
